<template>
  <div class="app-container upload-page">
    <el-row :gutter="16">
      <!-- 左：数据上传工作区 -->
      <el-col :md="16" :sm="24">
        <el-card shadow="never" class="panel">
          <div slot="header" class="panel__header">
            <i class="el-icon-upload panel__icon"></i>
            <div>
              <div class="panel__title">数据上传</div>
              <div class="panel__sub">提交结构化 JSON 或上传文件，系统将返回存储信息与去向提示</div>
            </div>
          </div>

          <!-- A. 结构化 JSON -->
          <el-form
            ref="formRef"
            :model="form"
            :rules="rules"
            label-width="96px"
            class="section"
          >
            <div class="section__title">
              <i class="el-icon-document"></i> 结构化数据（JSON）
            </div>

            <el-row :gutter="12">
              <el-col :md="10" :sm="24">
                <el-form-item prop="resourceType" label="资源类型">
                  <el-select v-model="form.resourceType" placeholder="请选择资源类型" filterable>
                    <el-option label="DID 文档" value="didDoc" />
                    <el-option label="访问控制规则" value="accessRule" />
                    <el-option label="权限申请" value="accessRequest" />
                  </el-select>
                </el-form-item>
              </el-col>

              <el-col :md="14" :sm="24" class="tips-col">
                <el-alert
                  :closable="false"
                  type="info"
                  show-icon
                  title="建议：JSON 内仅包含业务字段，ID/时间戳由后端生成。"
                />
              </el-col>
            </el-row>

            <el-form-item prop="jsonText" label="JSON 内容">
              <el-input
                v-model="form.jsonText"
                type="textarea"
                :rows="8"
                placeholder='示例：{"did":"did:example:123","controller":"did:example:xxx"}'
                class="mono"
              />
              <div class="editor-toolbar">
                <el-button size="mini" @click="formatJson" icon="el-icon-magic-stick">美化 JSON</el-button>
                <el-button size="mini" @click="minifyJson" icon="el-icon-scissors">压缩 JSON</el-button>
                <el-button size="mini" @click="copyJson" icon="el-icon-document-copy">复制</el-button>
              </div>
            </el-form-item>

            <el-form-item>
              <el-button
                :loading="loading"
                type="primary"
                icon="el-icon-check"
                @click="submitJson"
              >
                提交 JSON
              </el-button>
              <el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
            </el-form-item>
          </el-form>

          <el-divider></el-divider>

          <!-- B. 文件上传（拖拽上传区） -->
          <div class="section">
            <div class="section__title">
              <i class="el-icon-folder"></i> 文件上传
            </div>

            <el-upload
              class="uploader"
              drag
              :action="fileUploadUrl"
              name="file"
              :show-file-list="true"
              :headers="uploadHeaders"
              :data="fileExtraData"
              :before-upload="beforeFileUpload"
              :on-success="onFileSuccess"
              :on-error="onFileError"
              with-credentials
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">
                将文件拖到此处，或 <em>点击上传</em>
              </div>
              <div class="el-upload__tip">
                支持任意类型文件；后端返回访问 URL 或存储信息
              </div>
            </el-upload>

            <div v-if="lastUpload && lastUpload.fileId" class="after-upload">
              <el-tag type="success" effect="light">
                文件 ID：{{ lastUpload.fileId }}
              </el-tag>
              <el-button
                size="mini"
                type="primary"
                icon="el-icon-tickets"
                class="ml8"
                @click="applyViewFromLastFile"
              >
                一键申请阅览权
              </el-button>
            </div>
          </div>
        </el-card>
      </el-col>

      <!-- 右：结果与去向 -->
      <el-col :md="8" :sm="24">
        <el-card shadow="never" class="panel sticky">
          <div slot="header" class="panel__header">
            <i class="el-icon-notebook-2 panel__icon"></i>
            <div>
              <div class="panel__title">结果与去向</div>
              <div class="panel__sub">处理状态、落表位置、快速验证语句</div>
            </div>
          </div>

          <div v-if="!resultTip && !resultDetail" class="placeholder">
            <el-empty description="等待上传或提交..." />
          </div>

          <div v-else>
            <el-alert
              v-if="resultTip"
              :title="resultTip"
              type="success"
              show-icon
              :closable="false"
              class="mb12"
            />

            <el-timeline class="mb12">
              <el-timeline-item :timestamp="nowStr" placement="top">
                <el-card class="box-card compact">
                  <div class="box-card__title">处理详情</div>
                  <pre class="pre">{{ resultDetail }}</pre>
                </el-card>
              </el-timeline-item>

              <el-timeline-item :timestamp="nowStr" placement="top" v-if="whereHint">
                <el-card class="box-card compact">
                  <div class="box-card__title">数据去向</div>
                  <div v-html="whereHint"></div>
                </el-card>
              </el-timeline-item>
            </el-timeline>

            <div class="ops">
              <el-button size="mini" icon="el-icon-document-copy" @click="copyResult">
                复制结果 JSON
              </el-button>
              <el-button size="mini" icon="el-icon-delete" @click="clearResult">
                清空结果
              </el-button>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import request from '@/utils/request'

export default {
  name: 'UploadData',
  data() {
    return {
      loading: false,
      fileLoading: false,
      form: {
        resourceType: 'didDoc', // didDoc / accessRule / accessRequest
        jsonText: ''
      },
      rules: {
        resourceType: [{ required: true, message: '请选择资源类型', trigger: 'change' }],
        jsonText: [
          { required: true, message: '请填写 JSON 内容', trigger: 'blur' },
          { validator: (_, v, cb) => this.validateJson(v, cb), trigger: 'blur' }
        ]
      },

      resultTip: '',
      resultDetail: '',
      whereHint: '',
      lastUpload: null, // { fileId?, url?, rawResp }

      fileUploadUrl: process.env.VUE_APP_BASE_API + '/common/upload',
      uploadHeaders: {
        Authorization: 'Bearer ' + (localStorage.getItem('Admin-Token') || '')
      },
      fileExtraData: {}
    }
  },
  computed: {
    nowStr() {
      return new Date().toLocaleString()
    }
  },
  methods: {
    // —— 校验/工具 —— //
    validateJson(text, cb) {
      try {
        JSON.parse(text)
        cb()
      } catch (e) {
        cb(new Error('JSON 解析失败：' + e.message))
      }
    },
    formatJson() {
      if (!this.form.jsonText) return
      try {
        this.form.jsonText = JSON.stringify(JSON.parse(this.form.jsonText), null, 2)
        this.$message.success('已美化')
      } catch (e) {
        this.$message.error('美化失败：' + e.message)
      }
    },
    minifyJson() {
      if (!this.form.jsonText) return
      try {
        this.form.jsonText = JSON.stringify(JSON.parse(this.form.jsonText))
        this.$message.success('已压缩')
      } catch (e) {
        this.$message.error('压缩失败：' + e.message)
      }
    },
    copy(text) {
      const t = document.createElement('textarea')
      t.value = text
      document.body.appendChild(t)
      t.select()
      document.execCommand('copy')
      document.body.removeChild(t)
    },
    copyJson() {
      if (!this.form.jsonText) return
      this.copy(this.form.jsonText)
      this.$message.success('已复制 JSON')
    },
    copyResult() {
      if (!this.resultDetail) return
      this.copy(this.resultDetail)
      this.$message.success('已复制结果')
    },

    reset() {
      this.$refs.formRef && this.$refs.formRef.resetFields()
      this.clearResult()
      this.lastUpload = null
    },
    clearResult() {
      this.resultTip = ''
      this.resultDetail = ''
      this.whereHint = ''
    },

    // —— A. 提交结构化 JSON —— //
    async submitJson() {
      this.$refs.formRef.validate(async (ok) => {
        if (!ok) return
        this.loading = true
        this.clearResult()
        let payload = JSON.parse(this.form.jsonText)

        let url = ''
        if (this.form.resourceType === 'didDoc') url = '/did/document/create'
        else if (this.form.resourceType === 'accessRule') url = '/access/rule/create'
        else if (this.form.resourceType === 'accessRequest') url = '/access/request/create'

        try {
          const res = await request({ url, method: 'post', data: payload })
          const data = (res && res.data) || {}
          const newId = data.id || data.insertId || data.vcId || data.didId

          this.$message.success('数据上传成功')
          this.resultTip = `✅ 上传成功：${newId ? '新纪录 ID=' + newId : '已受理'}`
          this.resultDetail = JSON.stringify(res, null, 2)
          this.whereHint = this.buildWhereHint(url, newId)
        } catch (err) {
          this.$message.error('上传失败：' + (err.message || '网络错误'))
          this.resultDetail =
            (err && err.response && JSON.stringify(err.response.data, null, 2)) ||
            (err && err.stack) ||
            String(err)
        } finally {
          this.loading = false
        }
      })
    },

    // —— B. 文件上传 —— //
    beforeFileUpload() {
      this.fileLoading = true
      this.clearResult()
    },
    onFileSuccess(resp) {
      this.fileLoading = false
      // 若依 /common/upload 通常返回 { code:200, fileName, url }
      const url = (resp && (resp.url || (resp.data && resp.data.url))) || ''
      const fileId = resp && (resp.fileId || (resp.data && resp.data.id)) // 若你切到自定义上传接口可返回 id

      this.$message.success('文件上传成功')
      this.resultTip = '✅ 文件上传成功'
      this.resultDetail = JSON.stringify(resp, null, 2)
      this.whereHint = this.buildWhereHint('/common/upload', fileId, url)
      this.lastUpload = { fileId, url, rawResp: resp }
    },
    onFileError(err) {
      this.fileLoading = false
      this.$message.error('文件上传失败')
      this.resultDetail = String(err)
    },

    // —— C. “一键申请阅览权”（基于最近一次文件上传） —— //
    async applyViewFromLastFile() {
      if (!this.lastUpload || !this.lastUpload.fileId) {
        this.$message.warning('未获取到文件 ID，无法申请阅览权')
        return
      }
      try {
        const res = await request({
          url: '/access/request/create',
          method: 'post',
          data: {
            resource_type: 'file',
            resource_id: this.lastUpload.fileId,
            action: 'read',
            reason: '用户从上传页一键发起'
          }
        })
        this.$message.success('已提交阅览权限申请')
        // 叠加到时间线中
        const merged = {
          note: 'apply-view',
          response: res
        }
        const combined = {
          lastUpload: this.lastUpload,
          apply: merged
        }
        this.resultDetail = JSON.stringify(combined, null, 2)
        this.whereHint = this.buildWhereHint('/access/request/create')
      } catch (e) {
        this.$message.error('申请失败：' + (e.message || '网络错误'))
      }
    },

    // —— D. 去向提示 —— //
    buildWhereHint(url, id, fileUrl) {
      if (url.includes('/did/document/create')) {
        return [
          `<div>👉 已写入 <b>did_document</b> 表（DID 文档表）。</div>`,
          `<div class="hint-title">快速验证：</div>`,
          `<pre class="pre">SELECT * FROM did_document ORDER BY create_time DESC LIMIT 10;</pre>`
        ].join('')
      }
      if (url.includes('/access/rule/create')) {
        return [
          `<div>👉 已写入 <b>access_control_rule</b>（访问控制规则）。</div>`,
          `<pre class="pre">SELECT * FROM access_control_rule ORDER BY rule_id DESC LIMIT 10;</pre>`
        ].join('')
      }
      if (url.includes('/access/request/create')) {
        return [
          `<div>👉 已写入 <b>user_access_request</b>（用户访问申请）。</div>`,
          `<pre class="pre">SELECT * FROM user_access_request ORDER BY request_time DESC LIMIT 10;</pre>`
        ].join('')
      }
      if (url.includes('/common/upload')) {
        return [
          `<div>👉 文件位于服务器“上传目录”（由 <code>ruoyi.profile</code> 指定）。</div>`,
          fileUrl ? `<div>文件 URL：<a href="${fileUrl}" target="_blank">${fileUrl}</a></div>` : '',
          id
            ? `<div>文件 ID：<b>${id}</b>（你已切到自定义上传接口或后端已回传 ID）</div>`
            : `<div class="muted">若需要文件 ID：请改用自定义 /files/upload 接口并在后端入库 <code>file_resource</code>。</div>`
        ].join('')
      }
      return `<div>👉 已由后端受理（接口：${url}）。请查看后端持久化逻辑确认落表。</div>`
    }
  }
}
</script>

<style scoped>
/* 布局与区块 */
.upload-page { max-width: 1280px; margin: 0 auto; }
.panel { border: 1px solid var(--el-border-color, #ebeef5); }
.panel__header { display:flex; align-items:center; gap:12px; }
.panel__icon { font-size:18px; color:#5d86ff; }
.panel__title { font-weight:700; font-size:16px; line-height:1.2; }
.panel__sub { font-size:12px; color:#909399; }
.section { margin-top: 8px; }
.section__title { font-weight:600; margin: 2px 0 12px; display:flex; align-items:center; gap:6px; }

/* JSON 编辑器工具条 */
.editor-toolbar { margin-top:6px; display:flex; gap:8px; }
.mono :deep(textarea.el-textarea__inner) {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

/* 上传组件 */
.uploader { margin-top: 6px; }
.after-upload { margin-top: 8px; display:flex; align-items:center; }
.ml8 { margin-left: 8px; }

/* 右侧结果区 */
.sticky { position: sticky; top: 12px; }
.placeholder { padding: 12px 0; }
.mb12 { margin-bottom: 12px; }
.compact { padding: 8px; }
.box-card__title { font-weight:600; margin-bottom:6px; }
.pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  line-height: 1.6;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  font-size: 12px;
  background: var(--code-bg, #f7f8fa);
  border: 1px solid #ebeef5;
  border-radius: 6px;
  padding: 8px;
}
.hint-title { margin-top: 6px; color:#606266; font-size: 12px; }
.muted { color:#909399; font-size:12px; }
.tips-col :deep(.el-alert) { padding: 6px 8px; }
</style>
